/* eslint-disable no-case-declarations */
/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { CropperPosition, Dimensions, ExifTransform, ImageCroppedEvent, MoveTypes, MoveStart } from './type';
import { useImageCropper } from '../composition/use-image-cropper';
import { useCheckAspectRatio } from '../composition/use-check-aspect-ratio';
import { inject, onMounted, ref, SetupContext, watch, onUnmounted, Ref } from 'vue';
import { ImageCropperProps } from '../image-cropper.props';

export function useImageInfo(props: ImageCropperProps, context: SetupContext) {
    const { resizeCanvas, getTransformationsFromExifData } = useImageCropper();
    const NotifyService: any = inject('NotifyService');
    /** 裁剪的坐标 */
    const cropper = ref(props.cropper);
    /** scale缩放 rotate旋转 flipH横向反转 flipV垂直翻转 执行变化 */
    const transform = ref(props.transform);
    /** 裁剪最小宽高 */
    const cropperMinWidth = ref(props.cropperMinWidth);
    /** 保持长宽比例 */
    const maintainaspectRatio = ref(props.maintainAspectRatio);
    /** 宽高比例 width/height */
    const aspectRatio = ref(props.aspectRatio);
    /** 是否每次修改cropper的位置或大小时，cropper都会发出一个图像 */
    const autoCrop = ref(props.autoCrop);
    /** 背景色 */
    const backgroundColor = ref(props.backgroundColor);
    /** 裁剪后图片被调整为的宽高 */
    const resizeToWidth = ref(props.resizeToWidth);
    /** 启用这个选项将确保较小的图像不会被放大 */
    const onlyScaleDown = ref(props.onlyScaleDown);
    /** 是否在图像周围添加填充以使其适合长宽比 */
    const containWithinAspectRatio = ref(props.containWithinAspectRatio);
    /** 旋转画布 1 = 90deg */
    const canvasRotation = ref(props.canvasRotation);
    /** 输出图片格式 */
    const format = ref(props.format);
    /** 适用于使用jpeg或webp作为输出格式时。输入0到100之间的数字将决定输出图像的质量 */
    const imageQuality = ref(props.imageQuality);
    /** 裁剪后图片被调整为的高度 */
    const resizeToHeight = ref(props.resizeToHeight);
    /** 裁剪最小高度 */
    const cropperMinHeight = ref(props.cropperMinHeight);

    /** 图片url */
    const safeImgDataUrl = ref('');
    /** 是否正在加载 */
    const isLoading = ref(true);
    /** 图片是否可见 */
    const imageVisible = ref(true);
    /** 原始尺寸 */
    let originalSize: Dimensions;
    /** 改变后尺寸 */
    let transformedSize: Dimensions;
    /** 加载图片已用时间 */
    let setImageMaxSizeRetries = 0;
    /** 存储定时器 */
    let moveTimeout: any;
    /** 创建防抖函数 */
    let resizeTimeout: any;
    let originalImage: HTMLImageElement | null;
    const sourceImage = ref<HTMLDivElement | null>(null);
    const originalBase64 = ref('');
    const safeTransformStyle = ref('');
    const marginLeft = ref('0px');
    const transformedImage = ref();
    const maxSize = ref({ width: 100, height: 100 });
    const moveTypes = MoveTypes;
    let transformedBase64: string;
    let cropperScaledMinWidth = 20;
    let cropperScaledMinHeight = 20;
    let uploadError = false;
    let exifTransform: ExifTransform = { rotate: 0, flip: false };
    let moveStart: MoveStart = { active: false, type: null, position: null, x1: 0, y1: 0, x2: 0, y2: 0, clientX: 0, clientY: 0 };

    const _imageChangedEvent = ref(props.imageChangedEvent);
    const _imageURL = ref(props.imageURL);
    const _imageBase64 = ref(props.imageBase64);
    const _imageFile = ref(props.imageFile);

    /** 设置图片transform */
    function setCssTransform() {
        safeTransformStyle.value =
            'scaleX(' +
            (transform.value.scale || 1) * (transform.value.flipH ? -1 : 1) +
            ')' +
            'scaleY(' +
            (transform.value.scale || 1) * (transform.value.flipV ? -1 : 1) +
            ')' +
            'rotate(' +
            (transform.value.rotate || 0) +
            'deg)';
    }
    /** 初始化 */
    function initCropper(): void {
        imageVisible.value = false;
        transformedImage.value = null;
        safeImgDataUrl.value =
            '' +
            'oAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAU' +
            'AAarVyFEAAAAASUVORK5CYII=';
        moveStart = {
            active: false,
            type: null,
            position: null,
            x1: 0,
            y1: 0,
            x2: 0,
            y2: 0,
            clientX: 0,
            clientY: 0
        };
        maxSize.value = {
            width: 0,
            height: 0
        };
        originalSize = {
            width: 0,
            height: 0
        };
        transformedSize = {
            width: 0,
            height: 0
        };
        cropper.value.x1 = -100;
        cropper.value.y1 = -100;
        cropper.value.x2 = 10000;
        cropper.value.y2 = 10000;
    }
    /** 判断图片格式是否正确 */
    function isValidImageType(type: string): boolean {
        return /image\/(png|jpg|jpeg|bmp|gif|tiff|webp)/.test(type);
    }
    function getTransformedSize(): Dimensions {
        canvasRotation.value += exifTransform.rotate;
        if (containWithinAspectRatio.value && originalSize.width && originalSize.height) {
            // 填充空余
            if (canvasRotation.value % 2) {
                const minWidthToContain = originalSize.width * aspectRatio.value;
                const minHeightToContain = originalSize.height / aspectRatio.value;
                return {
                    width: Math.max(originalSize.height, minWidthToContain),
                    height: Math.max(originalSize.width, minHeightToContain)
                };
            }
            const minWidthToContain = originalSize.height * aspectRatio.value;
            const minHeightToContain = originalSize.width / aspectRatio.value;
            return {
                width: Math.max(originalSize.width, minWidthToContain),
                height: Math.max(originalSize.height, minHeightToContain)
            };
        }

        if (canvasRotation.value % 2) {
            return {
                height: originalSize.width,
                width: originalSize.height
            };
        }
        return {
            width: originalSize.width,
            height: originalSize.height
        };
    }
    /** 改变base64图片 */
    function transformImageBase64(): string {
        canvasRotation.value += exifTransform.rotate;
        const transformedSize = getTransformedSize();
        const canvas = document.createElement('canvas');
        if (transformedSize.width && transformedSize.height) {
            canvas.width = transformedSize.width;
            canvas.height = transformedSize.height;
        }
        const ctx = canvas.getContext('2d');
        if (originalSize.width && originalSize.height && originalImage) {
            ctx?.setTransform(exifTransform.flip ? -1 : 1, 0, 0, 1, canvas.width / 2, canvas.height / 2);
            ctx?.rotate(Math.PI * (canvasRotation.value / 2));
            ctx?.drawImage(originalImage, -originalSize.width / 2, -originalSize.height / 2);
        }
        return canvas.toDataURL();
    }
    /** 更新显示图片文件 */
    function setTransformedImage(transformedBase64Value: any): Promise<void> {
        return new Promise<void>((resolve) => {
            transformedBase64 = transformedBase64Value;
            safeImgDataUrl.value = transformedBase64Value;
            transformedImage.value = new Image();
            transformedImage.value.onload = () => {
                transformedSize.width = transformedImage.value?.naturalWidth;
                transformedSize.height = transformedImage.value?.naturalHeight;
                resolve();
            };
            transformedImage.value.src = transformedBase64;
        });
    }
    /** 原始图片转变 */
    function transformOriginalImage(): Promise<void> {
        if (!originalImage || !originalImage.complete || !exifTransform) {
            return Promise.reject(new Error('No image loaded'));
        }
        const transformedBase64 = transformImageBase64();
        return setTransformedImage(transformedBase64);
    }
    /** 判断文件信息，转换成base64 */
    function checkExifAndLoadBase64Image(imageBase64: string): void {
        const fail = (error: any) => {
            // NotifyService.error("图片上传错误，请重试");
            NotifyService.show({
                showCloseButton: false,
                timeout: 3000,
                animate: 'fadeIn',
                toasts: [{ type: 'string', title: '提示', msg: '图片上传错误，请重试' }]
            });
            isLoading.value = false;
            uploadError = true;
            context.emit('loadImageFailed');
            originalImage = null;
            originalBase64.value = '';
        };
        originalImage = new Image();
        originalImage.onload = () => {
            originalBase64.value = imageBase64;
            exifTransform = getTransformationsFromExifData(imageBase64);
            originalSize.width = originalImage?.naturalWidth;
            originalSize.height = originalImage?.naturalHeight;
            transformOriginalImage()
                .then(() => {
                    uploadError = false;
                })
                .catch(fail);
        };
        originalImage.onerror = fail;
        originalImage.src = imageBase64;
    }
    /** 处理图片 */
    function loadImage(imageBase64: string, imageType: string) {
        if (isValidImageType(imageType)) {
            uploadError = false;
            checkExifAndLoadBase64Image(imageBase64);
        } else {
            // NotifyService.error("图片类型不正确,请重试");
            NotifyService.show({
                showCloseButton: false,
                timeout: 3000,
                animate: 'fadeIn',
                toasts: [{ type: 'string', title: '提示', msg: '图片类型不正确,请重试' }]
            });
            isLoading.value = false;
            uploadError = true;
            context.emit('loadImageFailed');
        }
    }
    /** 加载图片文件 */
    function loadImageFile(file: any): void {
        const fileReader = new FileReader();
        fileReader.onload = (event: any) => loadImage(event.target.result, file.type);
        fileReader.readAsDataURL(file);
    }
    /** 从url获取文件 */
    function loadImageFromURL(url: string): void {
        const img = new Image();
        img.onerror = () => {
            // NotifyService.error("图片加载错误，请重试");
            NotifyService.show({
                showCloseButton: false,
                timeout: 3000,
                animate: 'fadeIn',
                toasts: [{ type: 'string', title: '提示', msg: '图片加载错误，请重试' }]
            });
            isLoading.value = false;
            uploadError = true;
            context.emit('loadImageFailed');
        };
        img.onload = () => {
            uploadError = false;
            const canvas = document.createElement('canvas');
            const innerContext = canvas.getContext('2d');
            canvas.width = img.width;
            canvas.height = img.height;
            innerContext?.drawImage(img, 0, 0);
            checkExifAndLoadBase64Image(canvas.toDataURL());
        };
        img.crossOrigin = 'anonymous';
        img.src = url;
    }
    /** 源图片加载完成 */
    function sourceImageLoaded() {
        return sourceImage.value && sourceImage.value && sourceImage.value.offsetWidth > 0;
    }
    /** 设置最大尺寸 */
    function setMaxSize(): void {
        if (sourceImage.value) {
            const sourceImageElement = sourceImage.value;
            maxSize.value.width = sourceImageElement.offsetWidth;
            maxSize.value.height = sourceImageElement.offsetHeight;
            marginLeft.value = 'calc(50% - ' + maxSize.value.width / 2 + 'px)';
        }
    }
    /** 设置裁切的小宽度 */
    function setCropperScaledMinWidth(): void {
        if (transformedImage.value && maxSize.value.width) {
            cropperScaledMinWidth =
                cropperMinWidth.value > 0
                    ? Math.max(20, (cropperMinWidth.value / transformedImage.value.width) * maxSize.value.width)
                    : 20;
        }
    }
    /** 设置裁切的小高度 */
    function setCropperScaledMinHeight(): void {
        if (maintainaspectRatio.value) {
            cropperScaledMinHeight = Math.max(20, cropperScaledMinWidth / aspectRatio.value);
        } else if (cropperMinHeight.value > 0 && transformedImage.value && maxSize.value.height) {
            cropperScaledMinHeight = Math.max(20, (cropperMinHeight.value / transformedImage.value.height) * maxSize.value.height);
        } else {
            cropperScaledMinHeight = 20;
        }
    }
    /** 设置裁剪区最小尺寸 */
    function setCropperScaledMinSize(): void {
        if (transformedImage.value) {
            setCropperScaledMinWidth();
            setCropperScaledMinHeight();
        } else {
            cropperScaledMinWidth = 20;
            cropperScaledMinHeight = 20;
        }
    }
    /** 获得图片位置坐标 */
    function getImagePosition(): CropperPosition {
        const sourceImageElement = sourceImage.value;
        const out = ref({ x1: 0, x2: 0, y1: 0, y2: 0 });
        if (sourceImageElement && transformedSize.width && transformedSize.height) {
            const ratio = transformedSize.width / sourceImageElement.offsetWidth;
            out.value = {
                x1: Math.round(cropper.value.x1 * ratio),
                y1: Math.round(cropper.value.y1 * ratio),
                x2: Math.round(cropper.value.x2 * ratio),
                y2: Math.round(cropper.value.y2 * ratio)
            };
            if (!containWithinAspectRatio.value) {
                out.value.x1 = Math.max(out.value.x1, 0);
                out.value.y1 = Math.max(out.value.y1, 0);
                out.value.x2 = Math.min(out.value.x2, transformedSize.width);
                out.value.y2 = Math.min(out.value.y2, transformedSize.height);
            }
        }

        return out.value;
    }
    /** 带填充的位置 */
    function getOffsetImagePosition(): CropperPosition {
        canvasRotation.value += exifTransform.rotate;
        const sourceImageElement = sourceImage.value;
        const out = ref({ x1: 0, x2: 0, y1: 0, y2: 0 });
        if (sourceImageElement && transformedSize.height && transformedSize.width && originalSize.height && originalSize.width) {
            const ratio = transformedSize.width / sourceImageElement.offsetWidth;
            let offsetX: number;
            let offsetY: number;

            if (canvasRotation.value % 2) {
                offsetX = (transformedSize.width - originalSize.height) / 2;
                offsetY = (transformedSize.height - originalSize.width) / 2;
            } else {
                offsetX = (transformedSize.width - originalSize.width) / 2;
                offsetY = (transformedSize.height - originalSize.height) / 2;
            }

            out.value = {
                x1: Math.round(cropper.value.x1 * ratio) - offsetX,
                y1: Math.round(cropper.value.y1 * ratio) - offsetY,
                x2: Math.round(cropper.value.x2 * ratio) - offsetX,
                y2: Math.round(cropper.value.y2 * ratio) - offsetY
            };
            if (!containWithinAspectRatio.value) {
                out.value.x1 = Math.max(out.value.x1, 0);
                out.value.y1 = Math.max(out.value.y1, 0);
                out.value.x2 = Math.min(out.value.x2, transformedSize.width);
                out.value.y2 = Math.min(out.value.y2, transformedSize.height);
            }
        }
        return out.value;
    }
    /** 获取重置后的比率 */
    function getResizeRatio(width: number, height: number): number {
        if (resizeToWidth.value > 0) {
            if (!onlyScaleDown.value || width > resizeToWidth.value) {
                return resizeToWidth.value / width;
            }
        } else if (resizeToHeight.value > 0) {
            if (!onlyScaleDown.value || height > resizeToHeight.value) {
                return resizeToHeight.value / height;
            }
        }
        return 1;
    }
    function getQuality(): number {
        return Math.min(1, Math.max(0, imageQuality.value / 100));
    }
    /** 转换为base64 */
    function cropToBase64(cropCanvas: HTMLCanvasElement): string {
        return cropCanvas.toDataURL('image/' + format.value, getQuality());
    }
    /** 裁剪动作 */
    function crop(): ImageCroppedEvent | null {
        if (sourceImage.value && sourceImage.value && transformedImage.value != null) {
            // 开始裁剪
            const imagePosition = getImagePosition();
            const width = imagePosition.x2 - imagePosition.x1;
            const height = imagePosition.y2 - imagePosition.y1;

            const cropCanvas = document.createElement('canvas') as HTMLCanvasElement;
            cropCanvas.width = width;
            cropCanvas.height = height;

            const ctx = cropCanvas.getContext('2d');
            if (ctx) {
                if (backgroundColor.value != null) {
                    ctx.fillStyle = backgroundColor.value;
                    ctx.fillRect(0, 0, width, height);
                }

                const scaleX = (transform.value.scale || 1) * (transform.value.flipH ? -1 : 1);
                const scaleY = (transform.value.scale || 1) * (transform.value.flipV ? -1 : 1);
                if (transformedSize.width && transformedSize.height) {
                    ctx.setTransform(scaleX, 0, 0, scaleY, transformedSize.width / 2, transformedSize.height / 2);
                    ctx.translate(-imagePosition.x1 / scaleX, -imagePosition.y1 / scaleY);
                    ctx.rotate(((transform.value.rotate || 0) * Math.PI) / 180);
                    ctx.drawImage(transformedImage.value, -transformedSize.width / 2, -transformedSize.height / 2);
                }
                const output: ImageCroppedEvent = {
                    width,
                    height,
                    imagePosition,
                    cropperPosition: { ...cropper.value }
                };
                if (containWithinAspectRatio.value) {
                    output.offsetImagePosition = getOffsetImagePosition();
                }
                const resizeRatio = getResizeRatio(width, height);
                if (resizeRatio !== 1) {
                    output.width = Math.round(width * resizeRatio);
                    output.height = maintainaspectRatio.value
                        ? Math.round(output.width / aspectRatio.value)
                        : Math.round(height * resizeRatio);
                    resizeCanvas(cropCanvas, output.width, output.height);
                }
                output.base64 = cropToBase64(cropCanvas);
                context.emit('imageCropped', output);
                return output;
            }
        }
        return null;
    }
    /** 判断是否裁切后发出图像 */
    function doAutoCrop(): void {
        if (autoCrop.value) {
            crop();
        }
    }
    /** 恢复裁剪区位置 */
    function resetCropperPosition(): void {
        const sourceImageElement = sourceImage.value;
        if (sourceImageElement) {
            if (!maintainaspectRatio.value) {
                cropper.value.x1 = 0;
                cropper.value.x2 = sourceImageElement.offsetWidth;
                cropper.value.y1 = 0;
                cropper.value.y2 = sourceImageElement.offsetHeight;
            } else if (sourceImageElement.offsetWidth / aspectRatio.value < sourceImageElement.offsetHeight) {
                cropper.value.x1 = 0;
                cropper.value.x2 = sourceImageElement.offsetWidth;
                const cropperHeight = sourceImageElement.offsetWidth / aspectRatio.value;
                cropper.value.y1 = (sourceImageElement.offsetHeight - cropperHeight) / 2;
                cropper.value.y2 = cropper.value.y1 + cropperHeight;
            } else {
                cropper.value.y1 = 0;
                cropper.value.y2 = sourceImageElement.offsetHeight;
                const cropperWidth = sourceImageElement.offsetHeight * aspectRatio.value;
                cropper.value.x1 = (sourceImageElement.offsetWidth - cropperWidth) / 2;
                cropper.value.x2 = cropper.value.x1 + cropperWidth;
            }
            doAutoCrop();
            imageVisible.value = true;
        }
    }
    function checkImageMaxSizeRecursively(): void {
        if (setImageMaxSizeRetries > 40) {
            // NotifyService.error("图片加载超时，请重试");
            NotifyService.show({
                showCloseButton: false,
                timeout: 3000,
                animate: 'fadeIn',
                toasts: [{ type: 'string', title: '提示', msg: '图片加载超时，请重试' }]
            });
            uploadError = true;
            isLoading.value = false;
            context.emit('loadImageFailed');
        } else if (sourceImageLoaded()) {
            uploadError = false;
            setMaxSize();
            setCropperScaledMinSize();
            resetCropperPosition();
            context.emit('cropperReady', { ...maxSize.value });
        } else {
            setImageMaxSizeRetries++;
            setTimeout(() => checkImageMaxSizeRecursively(), 50);
        }
    }
    /** 加载图片 加载20s没成功会抛出加载错误 */
    function imageLoadedInView(): void {
        if (transformedImage.value != null) {
            isLoading.value = false;
            context.emit('imageLoaded');
            setImageMaxSizeRetries = 0;
            setTimeout(() => checkImageMaxSizeRecursively());
        }
    }
    function resizeCropperPosition(): void {
        const sourceImageElement = sourceImage.value;
        if (
            (maxSize.value.width !== sourceImageElement?.offsetWidth || maxSize.value.height !== sourceImageElement?.offsetHeight) &&
            maxSize.value.width &&
            maxSize.value.height &&
            sourceImageElement
        ) {
            cropper.value.x1 = (cropper.value.x1 * sourceImageElement.offsetWidth) / maxSize.value.width;
            cropper.value.x2 = (cropper.value.x2 * sourceImageElement.offsetWidth) / maxSize.value.width;
            cropper.value.y1 = (cropper.value.y1 * sourceImageElement.offsetHeight) / maxSize.value.height;
            cropper.value.y2 = (cropper.value.y2 * sourceImageElement.offsetHeight) / maxSize.value.height;
        }
    }
    const onResize = () => {
        resizeCropperPosition();
        setMaxSize();
        setCropperScaledMinSize();
    };
    const debounceResizeHandler = () => {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(onResize, 300);
    };

    /** 在组件挂载时添加事件监听器 */
    onMounted(() => {
        window.addEventListener('resize', debounceResizeHandler);
        if (_imageURL.value) {
            initCropper();
            isLoading.value = true;
            loadImageFromURL(_imageURL.value);
        }
    });

    /** 在组件卸载时移除事件监听器 */
    onUnmounted(() => {
        window.removeEventListener('resize', debounceResizeHandler);
    });

    /** 停止移动图片 */
    function moveStop(): void {
        if (moveStart.active) {
            moveStart.active = false;
            doAutoCrop();
        }
    }

    function getClientX(event: any): number {
        return (event.touches && event.touches[0] ? event.touches[0].clientX : event.clientX) || 0;
    }

    function getClientY(event: any): number {
        return (event.touches && event.touches[0] ? event.touches[0].clientY : event.clientY) || 0;
    }
    /** 开始移动轮廓 */
    function startMove(event: any, moveType: MoveTypes, position: string | null = null): void {
        if (moveStart && moveStart.active) {
            return;
        }
        if (event.preventDefault) {
            event.preventDefault();
        }
        moveStart = {
            active: true,
            type: moveType,
            position,
            clientX: getClientX(event),
            clientY: getClientY(event),
            ...cropper.value
        };
    }
    /** 检查剪切位置 */
    function checkCropperPosition(maintainSize = false): void {
        if (cropper.value.x1 < 0) {
            cropper.value.x2 -= maintainSize ? cropper.value.x1 : 0;
            cropper.value.x1 = 0;
        }
        if (cropper.value.y1 < 0) {
            cropper.value.y2 -= maintainSize ? cropper.value.y1 : 0;
            cropper.value.y1 = 0;
        }
        if (cropper.value.x2 > maxSize.value.width) {
            cropper.value.x1 -= maintainSize ? cropper.value.x2 - maxSize.value.width : 0;
            cropper.value.x2 = maxSize.value.width;
        }
        if (cropper.value.y2 > maxSize.value.height) {
            cropper.value.y1 -= maintainSize ? cropper.value.y2 - maxSize.value.height : 0;
            cropper.value.y2 = maxSize.value.height;
        }
    }
    /** 移动 */
    function move(event: any) {
        const diffX = getClientX(event) - moveStart.clientX;
        const diffY = getClientY(event) - moveStart.clientY;
        cropper.value.x1 = moveStart.x1 + diffX;
        cropper.value.y1 = moveStart.y1 + diffY;
        cropper.value.x2 = moveStart.x2 + diffX;
        cropper.value.y2 = moveStart.y2 + diffY;
    }
    const { checkAspectRatio } = useCheckAspectRatio(cropper, maxSize, aspectRatio, moveStart);
    /** 调整大小 */
    function resize(event: any): void {
        const diffX = getClientX(event) - moveStart.clientX;
        const diffY = getClientY(event) - moveStart.clientY;
        switch (moveStart.position) {
        case 'left':
            cropper.value.x1 = Math.min(moveStart.x1 + diffX, cropper.value.x2 - cropperScaledMinWidth);
            break;
        case 'topleft':
            cropper.value.x1 = Math.min(moveStart.x1 + diffX, cropper.value.x2 - cropperScaledMinWidth);
            cropper.value.y1 = Math.min(moveStart.y1 + diffY, cropper.value.y2 - cropperScaledMinHeight);
            break;
        case 'top':
            cropper.value.y1 = Math.min(moveStart.y1 + diffY, cropper.value.y2 - cropperScaledMinHeight);
            break;
        case 'topright':
            cropper.value.x2 = Math.max(moveStart.x2 + diffX, cropper.value.x1 + cropperScaledMinWidth);
            cropper.value.y1 = Math.min(moveStart.y1 + diffY, cropper.value.y2 - cropperScaledMinHeight);
            break;
        case 'right':
            cropper.value.x2 = Math.max(moveStart.x2 + diffX, cropper.value.x1 + cropperScaledMinWidth);
            break;
        case 'bottomright':
            cropper.value.x2 = Math.max(moveStart.x2 + diffX, cropper.value.x1 + cropperScaledMinWidth);
            cropper.value.y2 = Math.max(moveStart.y2 + diffY, cropper.value.y1 + cropperScaledMinHeight);
            break;
        case 'bottom':
            cropper.value.y2 = Math.max(moveStart.y2 + diffY, cropper.value.y1 + cropperScaledMinHeight);
            break;
        case 'bottomleft':
            cropper.value.x1 = Math.min(moveStart.x1 + diffX, cropper.value.x2 - cropperScaledMinWidth);
            cropper.value.y2 = Math.max(moveStart.y2 + diffY, cropper.value.y1 + cropperScaledMinHeight);
            break;
        case 'center':
            const { scale } = event;
            const newWidth = Math.abs(moveStart.x2 - moveStart.x1) * scale;
            const newHeight = Math.abs(moveStart.y2 - moveStart.y1) * scale;
            const { x1 } = cropper.value;
            const { y1 } = cropper.value;
            cropper.value.x1 = Math.min(moveStart.clientX - newWidth / 2, cropper.value.x2 - cropperScaledMinWidth);
            cropper.value.y1 = Math.min(moveStart.clientY - newHeight / 2, cropper.value.y2 - cropperScaledMinHeight);
            cropper.value.x2 = Math.max(moveStart.clientX + newWidth / 2, x1 + cropperScaledMinWidth);
            cropper.value.y2 = Math.max(moveStart.clientY + newHeight / 2, y1 + cropperScaledMinHeight);
            break;
        }

        if (maintainaspectRatio.value) {
            checkAspectRatio();
        }
    }
    /** 移动图片 */
    function moveImg(event: any) {
        if (moveStart) {
            if (moveStart.active) {
                if (event.stopPropagation) {
                    event.stopPropagation();
                }
                if (event.preventDefault) {
                    event.preventDefault();
                }

                clearTimeout(moveTimeout);

                moveTimeout = setTimeout(() => {
                    if (moveStart.type === MoveTypes.Move) {
                        move(event);
                        checkCropperPosition(true);
                    } else if (moveStart.type === MoveTypes.Resize) {
                        resize(event);
                        checkCropperPosition(false);
                    }
                }, 300);
            }
        }
    }
    watch(_imageChangedEvent, (event) => {
        initCropper();
        if (event && event.target && event.target.files && event.target.files.length > 0) {
            isLoading.value = true;
            loadImageFile(event.target.files[0]);
        }
    });
    watch(_imageURL, (imageURL: string) => {
        if (imageURL) {
            initCropper();
            isLoading.value = true;
            loadImageFromURL(imageURL);
        } else {
            // NotifyService.error("图片路径为空");
            NotifyService.show({
                showCloseButton: false,
                timeout: 3000,
                animate: 'fadeIn',
                toasts: [{ type: 'string', title: '提示', msg: '图片路径为空' }]
            });
            isLoading.value = false;
            uploadError = true;
        }
    });
    watch(_imageBase64, (imageBase64: string) => {
        initCropper();
        isLoading.value = true;
        checkExifAndLoadBase64Image(imageBase64);
    });
    watch(_imageFile, (file) => {
        initCropper();
        if (file) {
            isLoading.value = true;
            loadImageFile(file);
        }
    });
    watch(
        () => [
            props.containWithinAspectRatio,
            props.canvasRotation,
            props.cropper,
            props.aspectRatio,
            props.transform,
            props.imageChangedEvent
        ],
        (
            [containWithinAspectRatio, canvasRotation, cropper, aspectRatio, transform, imageChangedEvent],
            [prevContainWithinAspectRatio, prevCanvasRotation, prevCropper, preAspectRatio, prevTransform, preImageChangedEvent]
        ) => {
            if (
                originalImage &&
                originalImage.complete &&
                exifTransform &&
                (containWithinAspectRatio !== prevContainWithinAspectRatio || canvasRotation !== prevCanvasRotation)
            ) {
                transformOriginalImage();
            }
            if (cropper !== prevCropper) {
                setMaxSize();
                setCropperScaledMinSize();
                checkCropperPosition(false);
                doAutoCrop();
            }
            if (aspectRatio !== preAspectRatio && imageVisible.value) {
                resetCropperPosition();
            }
            if (transform !== prevTransform) {
                setCssTransform();
                doAutoCrop();
            }
            if (imageChangedEvent !== preImageChangedEvent) {
                _imageChangedEvent.value = imageChangedEvent as Ref<Record<string, any>>;
            }
        }
    );

    return {
        uploadError,
        imageVisible,
        backgroundColor,
        sourceImage,
        safeImgDataUrl,
        safeTransformStyle,
        maxSize,
        cropper,
        marginLeft,
        moveTypes,
        isLoading,
        startMove,
        imageLoadedInView,
        moveStop,
        moveImg
    };
}
